home *** CD-ROM | disk | FTP | other *** search
- #!/usr/bin/python
- import dbus, sys, os, time, signal, re, glob
- import traceback
- import cups, cupshelpers
- import subprocess
- from syslog import *
- try:
- import usb
- except:
- pass
-
- def find_usblp_udi(udi):
- # Return always a UDI based on the usblp kernel module (has
- # "_printer_" in it). If the input UDI is from low-level USB,
- # find the corresponding usblp UDI.
- if udi.find ("_printer_") == -1:
- devnull = file ("/dev/null", "r+")
- command = "hal-device | grep '[0-9]: *udi *= *.%s.*_printer_' | cut -d \\' -f 2" % udi;
- try:
- p = subprocess.Popen (command,
- shell=True,
- stdin=devnull,
- stdout=subprocess.PIPE,
- stderr=devnull)
- (stdout, stderr) = p.communicate ()
- udi = stdout.split ('\n')[0].strip ()
- if udi.find ("_printer_") == -1:
- return None
- except:
- return None
- return udi
-
- def get_hal_property(udi, key):
- # Read out the value of a given key for a given HAL UDI
- devnull = file ("/dev/null", "r+")
- try:
- p = subprocess.Popen (["hal-get-property", "--udi", udi,
- "--key", key],
- stdin=devnull,
- stdout=subprocess.PIPE,
- stderr=devnull)
- (stdout, stderr) = p.communicate ()
- return stdout.strip ()
- except:
- return ""
-
- def get_hal_uri(udi):
- # udi is the UDI under which HAL reported the printer to us. The
- # "hal" CUPS backend only works with UDIs based on the usblp
- # kernel module and not with low-level UDIs. So if we are called
- # with a low-level UDI here we try to find the corresponding usblp
- # UDI here (contains "_printer_"). Then we return a valid CUPS URI
- # for the "hal" backend ("hal://<usblp-based HAL UDI>"). If we are
- # called with a low-level UDI and do not find the corresponding
- # usblp-based UDI, we return None.
- usblp_udi = find_usblp_udi(udi)
- if usblp_udi:
- return "hal://%s" % usblp_udi
- else:
- return None
-
- def get_hplip_uris_for_usb (fax=False, checkuri=None):
- hpuris = []
- env = dict()
- env.update (os.environ)
- env['LC_ALL'] = 'C'
- devnull = file ("/dev/null", "r+")
- try:
- p = subprocess.Popen (['lsusb'], env=env,
- stdin=devnull,
- stdout=subprocess.PIPE,
- stderr=devnull)
- (stdout, stderr) = p.communicate ()
- lsusboutput = stdout.split ('\n')
- except:
- if checkuri:
- return False
- else:
- return hpuris
- for line in lsusboutput:
- if (line.find ("ID 03f0:") < 0): continue
- bus = line[4:7]
- device = line[15:18]
- if fax:
- type="-f"
- else:
- type="-c"
- try:
- p = subprocess.Popen (["hp-makeuri", "-lnone",
- type, "%s:%s" % (bus, device)], env=env,
- stdin=devnull,
- stdout=subprocess.PIPE,
- stderr=devnull)
- (stdout, stderr) = p.communicate ()
- uri = stdout.split ('\n')[0].strip ()
- except:
- continue
- if (not uri): continue
- if checkuri and checkuri == uri:
- return True
- hpuris.append (uri)
- if checkuri:
- return False
- else:
- return hpuris
-
- class HalPrinter:
- def __init__(self):
- self.get_properties()
- self.uris = None
- self.hp_fax_uris = None
- try:
- self.cups_connection = cups.Connection()
- except RuntimeError, e:
- syslog (LOG_ERR,
- "Unable to connect to CUPS: '%s'. Is CUPS running?" % e)
- sys.exit (1)
-
- def get_properties(self):
- self.properties = {}
- for key, value in os.environ.iteritems():
- if key.startswith("HAL_PROP_"):
- name = key[9:].lower().replace("_", '.')
- self.properties[name] = value
- self.uid = os.getenv("UDI", "")
- if re.search ("_if\d+$", self.uid):
- syslog (LOG_DEBUG, "hal_lpadmin triggered by low-level USB device")
- else:
- syslog (LOG_DEBUG, "hal_lpadmin triggered by usblp kernel module")
- self.read()
-
- def fetch_device_id(self):
- p = self.properties
- devidstr = ''
- buses = usb.busses()
- usb_configuration_value = p.get ("usb.configuration.value")
- usb_interface_number = p.get ("usb.interface.number")
- for bus in buses:
- if int (bus.dirname) != int (p.get ("usb.bus.number")):
- continue
-
- for dev in bus.devices:
- if int (dev.filename) != int (p.get("usb.linux.device.number")):
- continue
-
- for config in dev.configurations:
- if (usb_configuration_value != None and
- (int (config.value) != int (usb_configuration_value))):
- continue
-
- for intf in config.interfaces:
- interfaceNumber = int (intf[0].interfaceNumber)
- if (usb_interface_number != None and
- int (interfaceNumber) !=
- int (usb_interface_number)):
- continue
-
- syslog (LOG_DEBUG, "Device %s:%s: %s" %
- (bus.dirname,
- dev.filename,
- p.get ("info.udi")))
- handle = dev.open ()
- #handle.setConfiguration (config)
- handle.claimInterface (intf[0])
- handle.setAltInterface (intf[0])
- intfno = intf[0].interfaceNumber
- alt = intf[0].alternateSetting
- devidarr = handle.controlMsg (requestType = 0xa1,
- request = 0,
- value = config.value - 1,
- index = (alt +
- (intfno << 8)),
- buffer = 4096,
- timeout = 100)
- siz = len(devidarr)
- len0 = devidarr[0]
- len1 = devidarr[1]
- devidlen = (((len0 & 255) << 8) +
- (len1 & 255))
- devidlen2 = (((len1 & 255) << 8) +
- (len0 & 255))
- if devidlen > siz:
- if devidlen2 > siz:
- devidlen = siz
- else:
- devidlen = devidlen2
- devidstr = ""
- for i in devidarr[2:]:
- devidstr += chr (i)
- syslog (LOG_DEBUG, "Device ID for %s:%s: %s" %
- (bus.dirname,
- dev.filename,
- devidstr))
- break
-
- if len (devidstr) > 0:
- break
-
- if usb_configuration_value != None:
- break
- break
- break
-
- return devidstr
-
- def read(self):
- p = self.properties
- fetch_id = False
- if p.get ("printer.vendor") == None or \
- p.get ("printer.product") == None or \
- p.get ("printer.description") == None or \
- p.get ("printer.commandset") == None:
- fetch_id = True
- usblp_udi = find_usblp_udi(self.uid)
- if usblp_udi:
- syslog (LOG_DEBUG,
- "Getting device ID from the usblp HAL entry ...")
- devidstr = "MFG:%s;MDL:%s;DES:%s;CMD:%s;" % \
- (get_hal_property(usblp_udi, "printer.vendor"),
- get_hal_property(usblp_udi, "printer.product"),
- get_hal_property(usblp_udi, "printer.description"),
- get_hal_property(usblp_udi, "printer.commandset").\
- replace(" ", ","))
- syslog (LOG_DEBUG, "Device ID for %s: %s" %
- (get_hal_property(usblp_udi, "printer.device"),
- devidstr))
- else:
- # Printer 1284 device URI not supplied by HAL, so we poll
- # it from the printer and add it to the HAL database
- # entry. This happens usually if the printer is detected
- # via low-level USB.
- if p.get ("usb.bus.number") == None or \
- p.get ("usb.linux.device.number") == None:
- fetch_id = False
- if fetch_id:
- try:
- syslog (LOG_DEBUG,
- "Polling device ID from the printer ...")
- devidstr = self.fetch_device_id ()
- except Exception, e:
- # We cannot read out the device ID from the
- # device, probably because the device is not
- # really a printer. So stop hal_lpadmin here
- # ignoring the device.
- syslog (LOG_DEBUG, "Failed to fetch device ID: %s" %
- str (e))
- syslog (LOG_DEBUG, "Ignoring device with UDI %s" %
- self.uid)
- sys.exit(0)
-
- if fetch_id:
- # Write it into the HAL database.
- try:
- self.device_id = devidstr
- id_dict = cupshelpers.parseDeviceID (devidstr)
- self.make = (id_dict["MFG"] or p.get("usb.vendor", "Unknown"))
- p["printer.vendor"] = self.make
- self.model = (id_dict["MDL"] or p.get("usb.product", "Unknown"))
- p["printer.product"] = self.model
- self.description = id_dict["DES"]
- p["printer.description"] = self.description
- self.name = self.get_name()
- self.faxname = self.name + "_fax"
- self.commandsets = id_dict["CMD"]
- p["printer.commandset"] = '\t'.join (self.commandsets)
- self.serial = (id_dict["SN"] or p.get("usb.serial", None))
- if self.serial != None:
- p["printer.serial"] = self.serial
-
- devnull = file ("/dev/null", "r+")
- env = dict()
- env.update (os.environ)
- env["LC_ALL"] = "C"
-
- for key in ("printer.vendor", "printer.product",
- "printer.description", "printer.serial"):
- if p.get (key) == None:
- continue
- try:
- pr = subprocess.Popen (["hal-set-property",
- "--udi=%s" % self.uid,
- "--key=%s" % key,
- "--string=%s" % p[key]],
- env=env,
- stdin=devnull,
- stdout=devnull,
- stderr=subprocess.STDOUT)
- pr.wait ()
- except:
- pass
- for cs in self.commandsets:
- try:
- pr = subprocess.Popen (["hal-set-property",
- "--udi=%s" % self.uid,
- "--key=printer.commandset",
- "--strlist-post=%s" % cs],
- env=env,
- stdin=devnull,
- stdout=devnull,
- stderr=subprocess.STDOUT)
- pr.wait ()
- except:
- pass
- syslog (LOG_DEBUG,
- "Written device ID into HAL database entry: "
- "MFG:%s;MDL:%s;DES:%s;CMD:%s;" %
- (p["printer.vendor"], p["printer.product"],
- p["printer.description"],
- p["printer.commandset"].replace("\t", ",")))
- except Exception, e:
- syslog (LOG_DEBUG,
- "Failed to write device ID into HAL database entry: %s"
- % str (e))
- fetch_id = False
-
- if not fetch_id:
- # Printer device ID is already available in the HAL database.
- # Either HAL has already put it there (triggered by the usblp
- # kernel module) or hal_lpadmin has read it from the printer
- # when it was turned on.
- syslog (LOG_DEBUG, "Using device ID from HAL database entry")
- self.make = (p.get("printer.vendor", "") or
- p.get("usb.vendor", "Unknown"))
- self.model = (p.get("printer.product", "") or
- p.get("usb.product", "Unknown"))
- self.description = p.get("printer.description", "")
- self.name = self.get_name()
- self.faxname = self.name + "_fax"
- self.commandsets = p.get('printer.commandset', '').split('\t')
- self.serial = p.get("printer.serial", "")
-
- # Reconstruct Device ID ready to put it into the PPD file.
- devidstr = ''
- for (field, value) in [("MFG:", self.make),
- ("MDL:", self.model),
- ("DES:", self.description),
- ("CMD:", reduce (lambda x, y: x + ',' + y,
- self.commandsets)),
- ("SN:", self.serial)]:
- if len (value) > 0:
- devidstr += field + value + ";"
-
- self.device_id = devidstr
-
- def get_name(self):
- # XXX check for unallowed chars
- if self.properties.has_key("usb.port_number"):
- name = "%s-%s" % (self.model,
- self.properties["usb.port_number"])
- else:
- name = self.model
- name = name.replace(" ", "-")
- name = name.replace("/", "-")
- return name.replace("#", "-")
-
- def get_cups_uris(self, removed=False):
- if self.uris != None:
- return self.uris
- uris = []
- available_usb_uris = []
- for backend in ("hal", "usb", "hp"):
- devnull = file ("/dev/null", "r+")
- command = "/usr/lib/cups/backend/%s | cut -s -d ' ' -f 2" % backend;
- try:
- p = subprocess.Popen (command,
- shell=True,
- stdin=devnull,
- stdout=subprocess.PIPE,
- stderr=devnull)
- (stdout, stderr) = p.communicate ()
- available_usb_uris = stdout.split ('\n') + \
- available_usb_uris
- except:
- pass
- udi = self.uid.lower ()
- make = ''
- model = ''
- serial = ''
- if self.properties.has_key("printer.vendor"):
- make = self.properties["printer.vendor"].lower ()
- if make == "hewlett-packard":
- make = "hp"
- elif make == "lexmark international":
- make = "lexmark"
- if self.properties.has_key("printer.product"):
- model = self.properties["printer.product"].lower ()
- if make and model.startswith (make):
- model = model[len (make):]
- model = model.lstrip ()
- model = model.rstrip ()
- if self.properties.has_key("printer.serial"):
- serial = self.properties["printer.serial"].lower ()
- for uri in available_usb_uris:
- if uri.lower ().find (udi) != -1:
- uris.append (uri)
- elif uri.lower ().find (serial) != -1:
- uris.append (uri)
- else:
- # If we arrive here, the printer's serial number did not
- # match the currently investigated URI. Skip this URI
- # if it contains another serial number
- if uri.lower().find("?serial=") != -1: continue
- nuri = re.sub(r"(\%\d\d)+", " ", uri.lower())
- nuri = re.sub(r"[^a-z0-9]+", " ", nuri)
- nmake = re.sub(r"[^a-z0-9]+", " ", make)
- nmodel = re.sub(r"[^a-z0-9]+", " ", model)
- if nuri.find (nmake) != -1 and nuri.find (nmodel) != -1:
- uris.append (uri)
- self.uris = uris
- return uris
-
- def get_cups_uri(self):
- try:
- return self.get_cups_uris()[0]
- except:
- return None
-
- def get_cups_hp_fax_uris(self, removed=False):
- if self.hp_fax_uris != None:
- return self.hp_fax_uris
- faxurisfound = 0
- if self.properties.has_key("printer.vendor"):
- vendor = self.properties["printer.vendor"].lower ()
- if (not removed and
- (vendor == "hewlett-packard" or vendor == "hp")):
- # We only can have a fax URI if we have an HP printer
- # supported by HPLIP
- try:
- # Try to find a matching HPLIP fax URI for the HPLIP
- # print URI for this device
- hpfaxuris = get_hplip_uris_for_usb (True)
- uris = self.get_cups_uris ()
- faxuris = []
- for uri in uris:
- if not uri.startswith ("hp:"): continue
- faxuri = uri.replace("hp:/", "hpfax:/")
- for furi in hpfaxuris:
- if faxuri == furi:
- faxurisfound = 1
- faxuris.append (faxuri)
- except:
- pass
-
- if faxurisfound == 1:
- self.hp_fax_uris = faxuris
- return faxuris
- else:
- return None
-
- def get_cups_hp_fax_uri(self):
- faxuris = self.get_cups_hp_fax_uris()
- if faxuris:
- return faxuris[0]
- else:
- return None
-
- def store_device_id_in_ppd(self):
- fname = self.cups_connection.getPPD(self.name)
- lines = file (fname).readlines ()
- attr = "*1284DeviceID:"
- has_1284_attr = reduce (lambda x, y: x or y,
- map (lambda x: x.startswith (attr)))
- outf = file (fname, 'w')
- written = False
- attrline = attr + ' ' + self.device_id + '\n'
- for line in lines:
- if not written:
- if has_1284_attr:
- if line.startswith (attr):
- # Replace existing attribute.
- line = attrline
- written = True
- else:
- if line == '\n':
- # Write attribute before first blank line.
- line = attrline + line
- written = True
-
- outf.write (line)
- if not written:
- outf.write (attrline)
- outf.close ()
- self.cups_connection.addPrinter(self.name, filename=fname)
- os.unlink (fname)
-
- def printer_is_our_hal_printer(self, name, printer):
- make = self.properties.get ("printer.vendor", None)
- model = self.properties.get ("printer.product", None)
- serial = self.properties.get ("printer.serial", None)
- if not serial:
- serial = self.properties.get ("info.udi", None)
- if not serial:
- serial = self.properties.get ("info.parent", None)
- if serial:
- res = re.search ("usb_device_[0-9a-fA-F]+_[0-9a-fA-F]+_([0-9a-zA-Z]+)", serial)
- if res:
- resg = res.groups()
- serial = resg[0]
- bus = self.properties.get ("linux.subsystem", None)
- udi = self.properties.get ("info.udi", None)
- if make:
- makel = make.lower ()
- if makel == "hewlett-packard":
- make = "HP"
- elif makel == "lexmark international":
- make = "Lexmark"
- if model:
- if model.startswith (make):
- model = model[len (make):]
- model = model.lstrip ()
- if printer.is_class:
- return False
- if (((model and
- (printer.device_uri.find (model.replace (" ", "%20")) \
- != -1 or
- printer.device_uri.find (model.replace (" ", "_")) \
- != -1)) and
- (not serial or printer.device_uri.find ("serial=") == -1 or
- (serial and
- printer.device_uri.find ("serial=" + serial) != -1)) and
- (not bus or
- printer.device_uri.find (bus) != -1)) or
- (udi and printer.device_uri.find (udi) != -1) or
- (serial and
- printer.device_uri.find ("serial=" + serial) != -1)):
- syslog (LOG_DEBUG,
- "Found configured printer: %s; URI: %s" %
- (name, printer.device_uri))
- return True
- return False
-
- def add(self):
- syslog (LOG_DEBUG, "add")
- make = self.properties.get ("printer.vendor", None)
- model = self.properties.get ("printer.product", None)
- serial = self.properties.get ("printer.serial", None)
- syslog (LOG_DEBUG, "Printer reported by HAL: %s %s %s" % (make, model, serial))
- printers = cupshelpers.getPrinters(self.cups_connection)
- printers_extra_info = None
- printer_exists = 0
- fax_exists = 0
- for name, printer in printers.iteritems():
- if self.printer_is_our_hal_printer(name, printer):
- if printer.device_uri.startswith("hpfax:"):
- fax_exists = 1
- else:
- printer_exists = 1
- syslog (LOG_DEBUG,
- "Not adding printer: %s already exists" % name)
- printer_exists = 1
- if not printer.enabled:
- if printers_extra_info == None:
- printers_extra_info = self.cups_connection.getPrinters()
- statemsg = printers_extra_info[name]["printer-state-message"]
- if statemsg.lower ().startswith ("unplugged"):
- syslog (LOG_INFO,
- "Re-enabling printer %s" % name)
- self.cups_connection.enablePrinter(name)
- else:
- syslog (LOG_INFO,
- "Printer %s exists but is disabled, reason: %s; "
- "use 'cupsenable %s' to enable it" % (name, statemsg, name))
-
- # Get some info needed to create CUPS queues and stop here if no new
- # queues are needed
- uris = self.get_cups_uris ()
- faxuris = self.get_cups_hp_fax_uris ()
- if printer_exists and (fax_exists or not faxuris):
- syslog (LOG_INFO, "No print queue setup needed for printer with UDI %s, as queues are already in place." % self.uid)
- return
- if not uris:
- syslog (LOG_INFO, "Could not treat printer with UDI %s, no CUPS URI found for it." % self.uid)
- return
- ppds = None
- syslog (LOG_DEBUG, "URIs: %s" % uris)
- syslog (LOG_DEBUG, "HPLIP Fax URIs: %s" % faxuris)
-
- # Make the name unique.
- if self.name in printers.keys ():
- suffix = 2
- while (self.name + str (suffix)) in printers.keys ():
- suffix += 1
- if suffix == 100:
- break
- self.name += str (suffix)
-
- # Make the faxname unique
- if self.faxname in printers.keys ():
- suffix = 2
- while (self.faxname + str (suffix)) in printers.keys ():
- suffix += 1
- if suffix == 100:
- break
- self.faxname += str (suffix)
-
- def wait_child (sig, stack):
- (pid, status) = os.wait ()
-
- signal.signal (signal.SIGCHLD, wait_child)
- pid = os.fork ()
- if pid == 0:
- # Child.
- if fax_exists == 0:
- # really new fax printer
- faxuri = self.get_cups_hp_fax_uri()
- else:
- faxuri = None
-
- if printer_exists == 0 or faxuri:
- # really new printer or fax - show tray icon with magnifier
- bus = dbus.SystemBus()
- try:
- syslog (LOG_DEBUG, "Calling GetReady")
- obj = bus.get_object("com.redhat.NewPrinterNotification",
- "/com/redhat/NewPrinterNotification")
- notification = dbus.Interface(obj,
- "com.redhat.NewPrinterNotification")
- notification.GetReady ()
- except dbus.DBusException, e:
- syslog (LOG_DEBUG, "D-Bus method call failed: %s" % e)
- notification = None
- else:
- notification = None
-
- status = 999
- if printer_exists == 0:
- # really new printer
-
- # If it is an HP printer, check whether it requires a
- # plugin and do not create a queue if it does
- plugin_needed = -1
- uri = self.get_cups_uri()
- if uri and uri.startswith ("hp:"):
- env = dict()
- env.update (os.environ)
- env['LC_ALL'] = 'C'
- devnull = file ("/dev/null", "r+")
- try:
- p = subprocess.Popen (["hp-info", "-i",
- "-d%s" % uri],
- env=env,
- stdin=devnull,
- stdout=subprocess.PIPE,
- stderr=devnull)
- properties = p.stdout.read ().split ("\n")
- except:
- # Problem executing command.
- plugin_needed = 0
- if plugin_needed < 0:
- hplip_version = None
- for line in properties:
- if line.find ("plugin ") >= 0:
- res = re.search ("(\d+)", line)
- if res:
- resg = res.groups()
- plugin_needed = int(resg[0])
- elif line.find ("HP Linux Imaging and Printing") >= 0:
- res = re.search ("(\d+\.\d+\.\d+\w*)", line)
- if res:
- resg = res.groups()
- hplip_version = resg[0]
- if plugin_needed >= 0:
- break
- if plugin_needed > 0 and hplip_version:
- # Check whether the plugin is already installed
- if glob.glob("/usr/share/hplip/data/plugin/*%s*plugin*" %
- hplip_version):
- if hplip_version.startswith("2"):
- try:
- f = open('/etc/hp/hplip.conf', 'r')
- for line in f:
- if line.strip ().startswith("plugin") and \
- line.strip ().endswith("1"):
- f.close()
- plugin_needed = 0
- f.close()
- except:
- pass
- else:
- plugin_needed = 0
- if uri and plugin_needed <= 0:
- # No HPLIP supported printer or no plugin needed, try to
- # find a driver and set up the print queue
- if ppds == None:
- cupsppds = self.cups_connection.getPPDs ()
- ppds = cupshelpers.ppds.PPDs (cupsppds)
- syslog (LOG_DEBUG, "Device ID: MFG:%s;MDL:%s;DES:%s;CMD:%s; URI:%s" %
- (self.make, self.model, self.description,
- reduce(lambda x, y: x + ',' + y, self.commandsets),
- uri))
- (status, ppdname) = \
- ppds.getPPDNameFromDeviceID (self.make, self.model,
- self.description,
- self.commandsets,
- uri)
- syslog (LOG_DEBUG, "PPD: %s; Status: %d" % (ppdname, status))
-
- info = "%s %s" % (self.make, self.model)
- self.device = uri
-
- if status == 0:
- self.cups_connection.addPrinter(self.name,
- device=self.device,
- ppdname=ppdname,
- info=info,
- location=os.uname ()[1])
- try:
- self.store_device_id_in_ppd ()
- except:
- pass
-
- cupshelpers.activateNewPrinter (self.cups_connection, self.name)
- syslog (LOG_INFO, "Added printer %s" % self.name)
- else:
- self.name = self.device
- syslog (LOG_INFO, "Did not add printer with URI %s, no exact model fit found" % self.name)
- else:
- self.name = uri
- syslog (LOG_INFO, "Did not add printer with URI %s, requires HPLIP plugin" % self.name)
-
- if faxuri:
- faxname = self.faxname
- if p == None:
- cupsppds = self.cups_connection.getPPDs ()
- p = cupshelpers.ppds.PPDs (cupsppds)
- (status, faxppd) = p.getPPDNameFromDeviceID ("HP", "Fax",
- "HP Fax", [], faxuri)
- info = "Fax queue for %s %s" % (self.make, self.model)
- self.cups_connection.addPrinter(faxname, device=faxuri,
- ppdname=faxppd, info=info,
- location=os.uname()[1])
- self.cups_connection.enablePrinter(faxname)
- self.cups_connection.acceptJobs(faxname)
- syslog (LOG_INFO, "Added fax printer %s" % faxname)
-
- if notification:
- if faxuri and printer_exists != 0:
- # Only fax queue
- n = faxname
- m = self.model + " (Fax)"
- else:
- n = self.name
- m = self.model
- try:
- notification.NewPrinter (status, n,
- self.make, m,
- self.description,
- reduce(lambda x, y: x + ',' + y,
- self.commandsets))
- except dbus.DBusException:
- pass
-
- elif pid == -1:
- pass # should handle error
-
- def remove(self):
- syslog (LOG_DEBUG, "remove")
- # Disable all print queues which print to the device which
- # we detected as having been removed. This prevents from
- # jobs being retried every 30 seconds. The jobs wait in the
- # queue until the device is reconnected and turned on.
- #
- # We cannot ask CUPS for the HPLIP URIs after having unplugged or
- # turned off the printer. So we take model name and serial number
- # provided by HAL and search the print queues whose URIs contain
- # this model name and serial number. These are then the queues
- # which we will disable.
- make = self.properties.get ("printer.vendor", None)
- model = self.properties.get ("printer.product", None)
- serial = self.properties.get ("printer.serial", None)
- syslog (LOG_DEBUG, "Printer reported by HAL: %s %s %s" % (make, model, serial))
- printers = cupshelpers.getPrinters(self.cups_connection)
- for name, printer in printers.iteritems():
- if self.printer_is_our_hal_printer(name, printer):
- if printer.enabled:
- # Check whether the parent UDI also disappeared
- parentdied = False
- parentudi = self.properties.get ("info.parent", None)
- if (parentudi and re.search ("_if\d+$", parentudi)):
- devnull = file ("/dev/null", "r+")
- try:
- pr = subprocess.Popen (["hal-device", parentudi],
- stdin=devnull,
- stdout=devnull,
- stderr=subprocess.STDOUT)
- pr.wait ()
- parentdied = (pr.returncode == 1);
- except:
- pass
- # Consider the device disconnected if either we were
- # triggered by the low-level UDI disappearing or in
- # case that we were triggered by the high-level (usblp
- # kernel module) UDI disappearing that then our parent
- # UDI (which is the low-level UDI) also disappeared.
- udi = self.properties.get ("info.udi", None)
- if (udi and re.search ("_if\d+$", udi)) or parentdied:
- self.cups_connection.disablePrinter(name,
- "Unplugged or turned off")
- syslog (LOG_INFO,
- "Disabled printer %s, as the corresponding device was unplugged or turned off" % (name))
-
- def configure(self):
- syslog (LOG_DEBUG, "configure")
- make, model = sys.stdin.readlines()
- if make[-1]=="\n": make = make[:-1]
- if model[-1]=="\n": model = model[:-1]
-
- cupsppds = self.cups_connection.getPPDs ()
- p = cupshelpers.ppds.PPDs (cupsppds)
- (status, ppdname) = p.getPPDNameFromDeviceID (make, model, "", "")
-
- if not ppdname:
- syslog (LOG_ERR,
- "User-selected make/model \"%s\" \"%s\" not found" %
- (make, model))
- return
-
- # add printer
- self.cups_connection.addPrinter(
- self.name, device=self.get_cups_uri(),
- ppdname=ppdname, info="Added by HAL",
- location=os.uname()[1])
- self.cups_connection.enablePrinter(self.name)
- self.cups_connection.acceptJobs(self.name)
- syslog (LOG_INFO,
- "Added printer %s with user-selected make/model" % self.name)
-
- class HalLpAdmin:
-
- def __init__(self):
- if len(sys.argv)!=2:
- return self.usage()
-
- if sys.argv[1]=="--add":
- self.addPrinter()
- elif sys.argv[1]=="--remove":
- self.removePrinter()
- elif sys.argv[1]=="--configure":
- self.configurePrinter()
- else:
- return self.usage()
-
- def usage(self):
- print "Usage: hal_lpadmin (--add|--remove|--configure)"
-
- def addPrinter(self):
- printer = HalPrinter()
- if printer.make:
- printer.add()
-
- def removePrinter(self):
- printer = HalPrinter()
- if printer.make:
- printer.remove()
-
- def configurePrinter(self):
- printer = HalPrinter()
- if printer.make:
- printer.configure()
-
- def main():
- openlog ("hal_lpadmin", 0, LOG_DAEMON)
- syslog (LOG_DEBUG, "Running hal_lpadmin")
- time.sleep (1) # Give HPLIP a chance to reconnect
- try:
- h = HalLpAdmin()
- except SystemExit, e:
- sys.exit (e)
- except:
- (type, value, tb) = sys.exc_info ()
- tblast = traceback.extract_tb (tb, limit=None)
- if len (tblast):
- tblast = tblast[:len (tblast) - 1]
- for line in traceback.format_tb (tb):
- syslog (LOG_ERR, line.strip ())
- extxt = traceback.format_exception_only (type, value)
- syslog (LOG_ERR, extxt[0].strip ())
-
- main()
-